#include "CompressionUtils.h"

#include <zlib.h>

#include <stdexcept>
#include <string>
#include <vector>

static std::vector<uint8_t> old_zlib_decompress(
    const std::vector<uint8_t>& data) {
    if (data.empty()) {
        return {};
    }

    // 分配一个较大的输出缓冲区（原始数据的4倍）

    std::vector<uint8_t> output(data.size() * 20);

    z_stream stream;

    // 初始化z_stream结构

    stream.zalloc = Z_NULL;

    stream.zfree = Z_NULL;

    stream.opaque = Z_NULL;

    stream.avail_in = static_cast<uInt>(data.size());

    stream.next_in = const_cast<Bytef*>(data.data());

    stream.avail_out = static_cast<uInt>(output.size());

    stream.next_out = output.data();

    // 使用gzip/zlib格式检测解压缩

    int ret = inflateInit2(&stream, 15 | 32);

    if (ret != Z_OK) {
        throw std::runtime_error("Failed to initialize zlib decompression: " +
                                 std::to_string(ret));
    }

    // 执行解压缩

    ret = inflate(&stream, Z_FINISH);

    // 清理

    inflateEnd(&stream);

    // 检查是否成功解压缩

    if (ret != Z_STREAM_END) {
        throw std::runtime_error("Zlib decompression failed: " +
                                 std::to_string(ret));
    }

    // 调整输出缓冲区大小

    output.resize(stream.total_out);

    return output;
}

// ZLib解压缩实现
std::vector<uint8_t> CompressionUtils::zlib_decompress(
    const std::vector<uint8_t>& data) {
    if (data.empty()) {
        return {};
    }

    z_stream stream;
    stream.zalloc = Z_NULL;
    stream.zfree = Z_NULL;
    stream.opaque = Z_NULL;

    // 初始化 zlib 流，使用 15 | 32 (自动检测 zlib/gzip 格式)
    // 必须在第一次调用 inflate 之前执行
    int ret = inflateInit2(&stream, 15 | 32);
    if (ret != Z_OK) {
        throw std::runtime_error("Failed to initialize zlib: " +
                                 std::to_string(ret));
    }

    // 设置输入数据
    stream.avail_in = static_cast<uInt>(data.size());
    // 避免 const_cast，直接使用 const data.data()
    stream.next_in =
        reinterpret_cast<Bytef*>(const_cast<uint8_t*>(data.data()));

    // 动态分配和管理输出缓冲区
    size_t chunk_size = data.size() * 4;  // 初始分配大小
    if (chunk_size < 1024)
        chunk_size = 1024;  //
                            // 确保至少有一个合理大小的起始块
    std::vector<uint8_t> output;
    output.reserve(chunk_size);  // 预留空间
    stream.avail_out = static_cast<uInt>(output.size());
    stream.next_out = output.data();

    do {
        // 如果输出缓冲区满了，扩大它
        if (stream.avail_out == 0) {
            size_t current_size = output.size();
            size_t new_size = current_size + chunk_size;

            output.resize(new_size);

            // 重新设置 stream 的输出指针和可用空间
            stream.avail_out = static_cast<uInt>(chunk_size);
            // next_out 应该指向新扩展的部分
            stream.next_out = output.data() + current_size;
        }

        // 核心解压缩调用
        ret = inflate(&stream, Z_NO_FLUSH);

        // 检查非流结束错误
        if (ret != Z_OK && ret != Z_STREAM_END && ret != Z_BUF_ERROR) {
            inflateEnd(&stream);
            throw std::runtime_error("Zlib decompression error: " +
                                     std::to_string(ret));
        }

    } while (ret != Z_STREAM_END);  // 当 Z_STREAM_END 返回时，表示解压完成

    // 清理
    inflateEnd(&stream);

    // 最终调整大小：只保留实际解压出的字节数
    output.resize(stream.total_out);

    return output;
}

// LZO解压缩实现
std::vector<uint8_t> CompressionUtils::lzo_decompress(
    const std::vector<uint8_t>& data, uint32_t decompressed_size) {
    // 注意：这里需要实际的LZO库支持
    // 以下是一个简化版本，实际实现需要引入LZO库并调用相应的API
    std::vector<uint8_t> output(decompressed_size);

    // 这里仅作为示例框架，实际项目中需要替换为正确的LZO解压缩代码
    // 例如使用lzo1x_decompress_safe等函数

    // 为了避免编译错误，这里简单复制数据（实际应用中需要删除这段代码并使用正确的LZO解压缩）
    size_t copy_size = std::min(data.size(), output.size());
    std::copy(data.begin(), data.begin() + copy_size, output.begin());

    return output;
}

// Adler32校验和实现
uint32_t CompressionUtils::adler32(const std::vector<uint8_t>& data) {
    const uint32_t BASE = 65521;  // 最大素数小于2^16
    const uint32_t NMAX = 5552;   // 每NMAX字节更新一次校验和

    uint32_t s1 = 1;  // 低16位
    uint32_t s2 = 0;  // 高16位

    size_t len = data.size();
    size_t pos = 0;

    while (len > 0) {
        size_t k = len < NMAX ? len : NMAX;
        len -= k;

        for (; k > 0; k--) {
            s1 += data[pos++];
            s2 += s1;
        }

        // 对BASE取模
        s1 %= BASE;
        s2 %= BASE;
    }

    // 组合两个16位值
    return (s2 << 16) | s1;
}
